<?php
namespace app\utils;
class GdImgPick{
	private $file;
    private $image;
    private $type;
    private $width;
    private $height;
    private $bits;
    private $mime;
	public function __construct($file){
		if (!extension_loaded('gd')) {
            throw new \Exception('Error: PHP GD is not installed!');
        }

        if (!file_exists($file))
            throw new \Exception('Error: Could not load image ' . $file . '!');
        $this->file = $file;

        $info = getimagesize($file);

        $this->width = $info[0];
        $this->height = $info[1];
        $this->bits = isset($info['bits']) ? $info['bits'] : '';
        $this->mime = isset($info['mime']) ? $info['mime'] : '';

        if ($this->mime == 'image/gif') {
            $this->image = imagecreatefromgif($file);
            $this->type = 'gif';
        } elseif ($this->mime == 'image/png') {
            $this->image = imagecreatefrompng($file);
            $this->type = 'png';
        } elseif ($this->mime == 'image/jpeg') {
            $this->image = imagecreatefromjpeg($file);
            $this->type = 'jpeg';
        }
	}

	/**
     *
     *
     * @return    string
     */
    public function getFile()
    {
        return $this->file;
    }

    /**
     *
     *
     * @return    array
     */
    public function getImage()
    {
        return $this->image;
    }

    /**
     *
     *
     * @return    string
     */
    public function getWidth()
    {
        return $this->width;
    }

    /**
     *
     *
     * @return    string
     */
    public function getHeight()
    {
        return $this->height;
    }

    /**
     *
     *
     * @return    string
     */
    public function getBits()
    {
        return $this->bits;
    }

    /**
     *
     *
     * @return    string
     */
    public function getMime()
    {
        return $this->mime;
    }

	public function saveAs($file, $quality = 100)
    {
    	if(empty($this->image) || empty($file)) return false;
    	if ($this->type == 'jpeg') {
            imagejpeg($this->image, $file, $quality);
        } elseif ($this->type == 'png') {
            imagepng($this->image, $file);
        } elseif ($this->type == 'gif') {
            imagegif($this->image, $file);
        }
        imagedestroy($this->image);
        return true;
    }
    public function save($quality=100){
        $file =$this->file;
        if(empty($this->image)) return false;
        if ($this->type == 'jpeg') {
            imagejpeg($this->image, $file, $quality);
        } elseif ($this->type == 'png') {
            imagepng($this->image, $file);
        } elseif ($this->type == 'gif') {
            imagegif($this->image, $file);
        }
        imagedestroy($this->image);
    }
    public function cropImage($targetFile, $width, $height){
    	$w  = $this->width - $width;
    	$h  = $this->height - $height;
    	if($w <=0){
    		return false;
    	}
    	$top_x = intval($w / 2);
    	$top_y = $h <=0 ? 0 : intval($h / 2);
    	$bottom_x = $top_x + $width;
    	$bottom_y = $top_y + $height;
    	$this->crop($top_x, $top_y,$bottom_x, $bottom_y);
    	$flag = $this->saveAs($targetFile);
    	return $flag;
    }
    
    /**
     *
     *
     * @param    int $top_x
     * @param    int $top_y
     * @param    int $bottom_x
     * @param    int $bottom_y
     */
    public function crop($top_x, $top_y, $bottom_x, $bottom_y)
    {
        $image_old = $this->image;
        if(empty($image_old)) return false;
        $this->image = imagecreatetruecolor($bottom_x - $top_x, $bottom_y - $top_y);
        @imagecopy($this->image, $image_old, 0, 0, $top_x, $top_y, $this->width, $this->height);
        imagedestroy($image_old);
        $this->width = $bottom_x - $top_x;
        $this->height = $bottom_y - $top_y;
    }

    /**
     *
     *
     * @param    int $width
     * @param    int $height
     * @param    string $default
     */
    public function resize($width = 0, $height = 0, $default = '')
    {
        if (!$this->width || !$this->height) {
            return;
        }

        $xpos = 0;
        $ypos = 0;
        $scale = 1;

        $scale_w = $width / $this->width;
        $scale_h = $height / $this->height;

        if ($default == 'w') {
            $scale = $scale_w;
        } elseif ($default == 'h') {
            $scale = $scale_h;
        } else {
            $scale = min($scale_w, $scale_h);
        }

        if ($scale == 1 && $scale_h == $scale_w && $this->mime != 'image/png') {
            return;
        }

        $new_width = (int)($this->width * $scale);
        $new_height = (int)($this->height * $scale);
        $xpos = (int)(($width - $new_width) / 2);
        $ypos = (int)(($height - $new_height) / 2);

        $image_old = $this->image;
        $this->image = imagecreatetruecolor($width, $height);

        if ($this->mime == 'image/png') {
            imagealphablending($this->image, false);
            imagesavealpha($this->image, true);
            $background = imagecolorallocatealpha($this->image, 255, 255, 255, 127);
            imagecolortransparent($this->image, $background);
        } else {
            $background = imagecolorallocate($this->image, 255, 255, 255);
        }

        imagefilledrectangle($this->image, 0, 0, $width, $height, $background);

        imagecopyresampled($this->image, $image_old, $xpos, $ypos, 0, 0, $new_width, $new_height, $this->width, $this->height);
        imagedestroy($image_old);

        $this->width = $width;
        $this->height = $height;
    }

    public function resize_b($width = 0, $height = 0, $default = '')
    {
        if (!$this->width || !$this->height) {
            return;
        }

        $xpos = 0;
        $ypos = 0;
        $scale = 1;

        $scale_w = $width / $this->width;
        $scale_h = $height / $this->height;

        if ($default == 'w') {
            $scale = $scale_w;
        } elseif ($default == 'h') {
            $scale = $scale_h;
        } else {
            $scale = min($scale_w, $scale_h);
        }

        if ($scale == 1 && $scale_h == $scale_w && $this->mime != 'image/png') {
            return;
        }

        $new_width = (int)($this->width * $scale);
        $new_height = (int)($this->height * $scale);
        $xpos = (int)(($width - $new_width) / 2);
        $ypos = (int)(($height - $new_height) / 2);

        $image_old = $this->image;
        $this->image = imagecreatetruecolor($width, $height);

        if ($this->mime == 'image/png') {
            imagealphablending($this->image, false);
            imagesavealpha($this->image, true);
            $background = imagecolorallocatealpha($this->image, 219, 221, 225, 127);
            imagecolortransparent($this->image, $background);
        } else {
            $background = imagecolorallocate($this->image, 219, 221, 225);
        }

        imagefilledrectangle($this->image, 0, 0, $width, $height, $background);

        imagecopyresampled($this->image, $image_old, $xpos, $ypos, 0, 0, $new_width, $new_height, $this->width, $this->height);
        imagedestroy($image_old);

        $this->width = $width;
        $this->height = $height;
    }

    /**
     *
     *
     * @param    int $width
     * @param    int $height
     * @param    string $default
     */
    public function resize_blur($width = 0, $height = 0, $default = '')
    {
        if (!$this->width || !$this->height) {
            return;
        }

        $image_old = $this->image;

        $wor = imagesx($image_old);
        $hor = imagesy($image_old);
        $this->image = imagecreatetruecolor($width, $height);

        $maxfact = max($width / $wor, $height / $hor);
        $new_w = $wor * $maxfact;
        $new_h = $hor * $maxfact;
        imagecopyresampled($this->image, $image_old, -(($new_w - $width)), -(($new_h - $height)), 0, 0, $new_w, $new_h, $wor/20, $hor/20);

        // Blur Image
        for ($x = 1; $x <= 40; $x++) {
            imagefilter($this->image, IMG_FILTER_GAUSSIAN_BLUR);
        }
//    imageconvolution($back, [[100, 100, 100],
//        [100, 100, 100],
//        [100, 100, 100]], 900, 0);
        imagefilter($this->image, IMG_FILTER_SMOOTH, -4);
//    imagefilter($back, IMG_FILTER_BRIGHTNESS, 10);

        $minfact = min($width / $wor, $height / $hor);
        $new_w = $wor * $minfact;
        $new_h = $hor * $minfact;

        $front = imagecreatetruecolor($new_w, $new_h);
        imagecopyresampled($front, $image_old, 0, 0, 0, 0, $new_w, $new_h, $wor, $hor);

        imagecopymerge($this->image, $front, -(($new_w - $width) / 2), -(($new_h - $height) / 2), 0, 0, $new_w, $new_h, 100);
        imagedestroy($front);
        imagedestroy($image_old);

        $this->width = $width;
        $this->height = $height;
    }

    /**
     *
     *
     * @param    string $watermark
     * @param    string $position
     */
    public function watermark($watermark, $position = 'bottomright', $opacity = 50)
    {
        if($watermark->getWidth() > $this->width || $watermark->getHeight() > $this->height ){
            $watermark->resize(ceil($this->width/2), ceil($this->height/2));
        }

        imagealphablending($this->image, true);
        imagesavealpha($this->image, true);

        switch ($position) {
            case 'all':
                // 計算重複覆蓋的行和列數
                $repeatRows = ceil($this->height / $watermark->getWidth());
                $repeatCols = ceil($this->width / $watermark->getHeight());
                for ($row = 0; $row < $repeatRows; $row++) {
                    for ($col = 0; $col < $repeatCols; $col++) {
                        // 計算當前位置
                        $x = $col * $watermark->getWidth();
                        $y = $row * $watermark->getHeight();
                        // 複製水印到目標圖片的位置
                        $this->merge($watermark, $x, $y, $opacity);
                        // imagecopy($image, $watermark, $x, $y, 0, 0, $watermarkWidth, $watermarkHeight);
                    }
                }
                break;
            case 'topleft':
                $watermark_pos_x = 0;
                $watermark_pos_y = 0;
                break;
            case 'topcenter':
                $watermark_pos_x = intval(($this->width - $watermark->getWidth()) / 2);
                $watermark_pos_y = 0;
                break;
            case 'topright':
                $watermark_pos_x = $this->width - $watermark->getWidth();
                $watermark_pos_y = 0;
                break;
            case 'middleleft':
                $watermark_pos_x = 0;
                $watermark_pos_y = intval(($this->height - $watermark->getHeight()) / 2);
                break;
            case 'middlecenter':
                $watermark_pos_x = intval(($this->width - $watermark->getWidth()) / 2);
                $watermark_pos_y = intval(($this->height - $watermark->getHeight()) / 2);
                break;
            case 'middleright':
                $watermark_pos_x = $this->width - $watermark->getWidth();
                $watermark_pos_y = intval(($this->height - $watermark->getHeight()) / 2);
                break;
            case 'bottomleft':
                $watermark_pos_x = 0;
                $watermark_pos_y = $this->height - $watermark->getHeight();
                break;
            case 'bottomcenter':
                $watermark_pos_x = intval(($this->width - $watermark->getWidth()) / 2);
                $watermark_pos_y = $this->height - $watermark->getHeight();
                break;
            case 'bottomright':
            default:
                $watermark_pos_x = $this->width - $watermark->getWidth();
                $watermark_pos_y = $this->height - $watermark->getHeight();
                break;
        }
        if($position != 'all'){
            // imagecopy($this->image, $watermark->getImage(), $watermark_pos_x, $watermark_pos_y, 0, 0, $watermark->getWidth(), $watermark->getHeight());

            // imagecopyresampled($this->image, $watermark->getImage(), $watermark_pos_x, $watermark_pos_y, 0, 0, $watermark->getWidth(), $watermark->getHeight(), $this->width, $this->height);
            $this->merge($watermark, $watermark_pos_x, $watermark_pos_y, $opacity);
        }
        imagedestroy($watermark->getImage());
    }

    /**
     *
     *
     * @param    int $degree
     * @param    string $color
     */
    public function rotate($degree, $color = 'FFFFFF')
    {
        $rgb = $this->html2rgb($color);

        $this->image = imagerotate($this->image, $degree, imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]));

        $this->width = imagesx($this->image);
        $this->height = imagesy($this->image);
    }

    /**
     *
     *
     */
    private function filter()
    {
        $args = func_get_args();

        call_user_func_array('imagefilter', $args);
    }

    /**
     *
     *
     * @param    string $text
     * @param    int $x
     * @param    int $y
     * @param    int $size
     * @param    string $color
     */
    private function text($text, $x = 0, $y = 0, $size = 5, $color = '000000')
    {
        $rgb = $this->html2rgb($color);

        imagestring($this->image, $size, $x, $y, $text, imagecolorallocate($this->image, $rgb[0], $rgb[1], $rgb[2]));
    }

    /**
     *
     *
     * @param    object $merge
     * @param    object $x
     * @param    object $y
     * @param    object $opacity
     */
    private function merge($merge, $x = 0, $y = 0, $opacity = 100)
    {
        imagecopymerge($this->image, $merge->getImage(), $x, $y, 0, 0, $merge->getWidth(), $merge->getHeight(), $opacity);
    }

    /**
     *
     *
     * @param    string $color
     *
     * @return    array
     */
    private function html2rgb($color)
    {
        if ($color[0] == '#') {
            $color = substr($color, 1);
        }

        if (strlen($color) == 6) {
            list($r, $g, $b) = array($color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5]);
        } elseif (strlen($color) == 3) {
            list($r, $g, $b) = array($color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2]);
        } else {
            return false;
        }

        $r = hexdec($r);
        $g = hexdec($g);
        $b = hexdec($b);

        return array($r, $g, $b);
    }
}